package com.icesoft.core.web.suppose.safehttp;

import com.icesoft.core.Const;
import com.icesoft.core.common.helper.Resp;
import com.icesoft.core.web.base.BaseAnnotationInterceptor;
import com.icesoft.core.web.helper.ResponseUtils;
import com.icesoft.core.web.suppose.csrf.TimeUnitNonceStrFilter;
import com.icesoft.core.web.suppose.safehttp.filter.HeadSafeRequestFilter;
import com.icesoft.core.web.suppose.safehttp.filter.ParamSafeRequestFilter;
import com.icesoft.core.web.suppose.safehttp.request.SafeHttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.TreeMap;

@Slf4j
@Component
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@AllArgsConstructor
public class SafeRequestInterceptor extends BaseAnnotationInterceptor<SafeRequest> {
    private final List<HeadSafeRequestFilter> headFilters;
    private final List<ParamSafeRequestFilter> paramFilters;
    private final TimeUnitNonceStrFilter timeUnitNonceStrFilter;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod,
                             SafeRequest safeRequest) {
        if (safeRequest == null || safeRequest.disable()) {
            return true;
        }
        log.debug("safeRequest请求：{}, clientType={}, versionCode={}", request.getRequestURI(),
                request.getHeader("clientType"), request.getHeader("versionCode"));
        for (HeadSafeRequestFilter appFilter : headFilters) {
            if (!appFilter.headFilter(request, response)) {
                return false;
            }
        }
        TreeMap<String, String> paramMap;
        SafeHttpServletRequest bcRequest = (SafeHttpServletRequest) request.getAttribute(SafeHttpServletRequest.ATTR_NAME);
        try {
            paramMap = bcRequest.resolveParam();
        } catch (IOException e) {
            log.error("IO异常", e);
            return false;
        }

        if (paramMap == null) {
            ResponseUtils.writeJson(response, Resp.error("json格式错误"));
            return false;
        }
        log.debug("请求参数：{}", paramMap);
        if (!timeUnitNonceStrFilter.filter(bcRequest, response)) {
            log.debug("timeUnitNonceStr校验失败");
            return false;
        }
        for (ParamSafeRequestFilter appFilter : paramFilters) {
            if (!appFilter.paramFilter(request, response, paramMap)) {
                return false;
            }
        }
        request.setAttribute(Const.REQUEST_RESOLVER_PARAM_MAP_NAME, paramMap);
        return true;
    }

}
